/***********************************************************************
 * 描述: 	年龄计算类,可以根据生日计算当前年龄,也可以根据年龄反推生日。PImpl模式实现
 * File:    agecalc.h
 * Author:  chenanqi@mozihealthcare.cn
 * Date:    2025/9/22 13:48
 * Update:
 **********************************************************************/
#ifndef AGECALC_H
#define AGECALC_H
#include <optional>
#include <QString>
#include <common/export.h>

class QDateTime;

class CXI_COMMON_EXPORT AgeCalc
{
	enum class AgeCalcType
	{
		Y = 1,// 年
		YM,   // 年月
		M,    // 月
		MD,   // 月日
		D,    // 日
		DH,   // 日时
		H,    // 时
		HMI   // 时分
	};

public:
	/**
	 * 根据年龄代码获取年龄
	 * 有三个区间
	 * 1. 大于14岁只显示到岁
	 * 2. 大于1岁小于14岁显示xx岁xx月。如果月 = 0则显示到岁即可
	 * 3. 小于1岁显示xx月xx天。如果天 = 0则显示到月即可。如果全为0直接返回1天
	 * @param code 年龄代码
	 * @return 返回年龄
	 */
	static QString getAgeByCodeInDH(const QString& code);

	/**
	 * 根据年龄代码获取年龄
	 * 例如 01010221432 要返回10岁2月1日4时
	 * 如果 showMinute=true,需要显示分钟,返回10岁2月1日4时2分
	 * 如果某一位是0,不显示该位
	 * @param code 年龄代码
	 * @param showMinute 是否显示分钟
	 * @return 返回具体年龄
	 */
	static QString getAgeByCode(const QString& code, bool showMinute = false);

	/**
	 * 根据出生日期和计算日期获取年龄代码
	 * 可以在网站验证 https://www.freeagecalculator.com/zh-cn/
	 * @param birthDay 出生日期
	 * @param calcDay 计算日期
	 * @param showMinute 是否显示分钟
	 * @return 返回年龄代码
	 */
	static QString getAgeCode(const QDateTime& birthDay, const QDateTime& calcDay, bool showMinute = false);

	/**
	 * 根据基准日期计算出生日期 (重载实现)
	 * @param date 基准日期
	 * @param year 年
	 * @param month 月
	 * @param day 日
	 * @param hour 时
	 * @param minute 分
	 * @return 返回出生日期
	 */
	static QDateTime calcBirthDay(const QDateTime& date, std::optional<int> year, std::optional<int> month, std::optional<int> day, std::optional<int> hour, std::optional<int> minute);
	// 重载
	static QDateTime calcBirthDay(const QDateTime& date, std::optional<int> year, std::optional<int> month, std::optional<int> day, std::optional<int> hour);
	// 重载
	static QDateTime calcBirthDay(const QDateTime& date, std::optional<int> year, std::optional<int> month, std::optional<int> day);
	// 重载
	static QDateTime calcBirthDay(const QDateTime& date, std::optional<int> year, std::optional<int> month);
	// 重载
	static QDateTime calcBirthDay(const QDateTime& date, std::optional<int> year);

	/**
	 * 年龄计算方法：通过出生日期和指定日期计算年龄描述
	 * @param birthday 出生日期
	 * @param calcDay 指定日期
	 * @return 年龄描述
	 */
	static QString getAgeString(std::optional<QDateTime> birthday,std::optional<QDateTime> calcDay);

	/**
	 * 获取年龄
	 * @param birthDay 生日
	 * @param calcDay 计算日期
	 * @param formatStr 格式字符串
	 * @param isEmr 病历
	 * @param zeroUnit 年龄0岁单位
	 * @return
	 */
	static QString getAge(std::optional<QDateTime> birthDay, std::optional<QDateTime> calcDay, const QString& formatStr, bool isEmr = false, const QString& zeroUnit = QString());

	/**
	 * 首页需要
	 * @param birthDay 生日(可空)
	 * @param calcDay 计算日期(可空)
	 * @return 年龄描述
	 */
	static QString getNewBabyAgeString(std::optional<QDateTime> birthDay, std::optional<QDateTime> calcDay);
};


#endif//AGECALC_H
